
import sys
import os

from .token_extractor import Example,IndexFile,load_as_json,extract_keyword
import src.codeql_tools.config as config


index_file=IndexFile()
example_buffer={}
buffer_list=[]

def get_examples(data_path):
    global buffer_list,example_buffer
    if data_path not in example_buffer:
        example_buffer[data_path]=list(load_as_json(data_path))
        buffer_list.insert(0,data_path)
        
        if len(buffer_list)>50:
            example_buffer.pop(buffer_list[-1])
            buffer_list=buffer_list[:-1]
    
    return example_buffer[data_path]
    
def set_index_file(path):
    global index_file
    #index_file=extractor.IndexFile()
    index_file.load(path)

def indexof(block_id,source_path,number):
    if source_path in index_file.indexes[block_id]:
        return index_file.indexes[block_id][source_path][number]
    else:
        return None 
    
def source_iter(block_number,source_path,lines):
    number=0
    no_exist_counter=0
    block_id=str(block_number)
    result=[]
    
    #print(source_path,len(lines))
    
    for i,line in enumerate(lines):
        if line.startswith('def '):
            function_name=line[:line.find('(')+1]
            #print(line)
            #print(function_name,number)
            source_path_in_index=source_path
            
            if source_path_in_index in index_file.indexes[block_id]:
                if number >= len(index_file.indexes[block_id][source_path_in_index]):
                    print(function_name)
                    print(f'{number}:{source_path_in_index}:{i}')
                result.append((function_name,index_file.indexes[block_id][source_path_in_index][number]))
            else:
                print("{} in {} no_exists!".format(function_name,source_path))
                no_exist_counter+=1
            number+=1
    
    return result,no_exist_counter,source_path

def dir_iter(dir_path,block_number):
    dir_path='{}/{}'.format(dir_path,block_number)
    filenames=os.listdir(dir_path)
    for filename in filenames:
        full_filename='{}/{}'.format(dir_path,filename)
        f=open(full_filename,'r',errors='ignore')
        lines=[l for l in f]
        f.close()
        
        yield source_iter(block_number,full_filename,lines)

def dataset_iter(dir_path):
    for i in range(1,100):
        target_dir='{}/{}'.format(dir_path,i)
        print(f"try search {target_dir}.")
        group_number=1
        if not os.path.exists(target_dir):
            break
        print("in directory {}".format(target_dir))
        while True:
            target_group='{}/{}'.format(target_dir,group_number)
            if not os.path.exists(target_group):
                break
            
            yield dir_iter(target_dir,group_number)  
            group_number+=1
            
def validate(dir_path):
    total_error_number=0
    miss_match_number=0
    for i in range(1,10):
        target_dir='{}/{}'.format(dir_path,i)
        group_number=1
        if not os.path.exists(target_dir):
            break
        print("in directory {}".format(target_dir))
        while True:
            target_group='{}/{}'.format(target_dir,group_number)
            if not os.path.exists(target_group):
                break
            
            print('{} is in validate.'.format(target_group))
            iterator= dir_iter(target_dir,group_number)
            
            
            for index,error_number,source_path in iterator:
                total_error_number+=error_number
                for function_name,(batch_number,data_path,data_number) in index:
                    examples=get_examples(data_path)          
                    example=Example(examples[data_number])
                    keyword_function_name=extract_keyword(function_name)
                    if example.get_function_name() != keyword_function_name:
                        miss_match_number+=1
                        print("source {} miss match with index: {}|{}".format(source_path,keyword_function_name,example.get_function_name()))
            group_number+=1
    
    
    print("validate result:")
    print("error number: {}".format(total_error_number))
    print("miss match number: {}".format(miss_match_number))



# def dataset_mapping(dir_path):
#     
        
if __name__=="__main__":
    args_length=len(sys.argv)
    if args_length==1:
        set_index_file("indexes_eval.json")
        validate(config.code_source)

    elif args_length==2:
        if sys.argv[1]=="test_train":
            set_index_file("indexes_train.json")
            validate(config.code_source)
            
        elif sys.argv[1]=="test_dev":
            set_index_file("indexes_dev.json")
            validate(config.code_source)
        else:
            print("input error.")
    